#include <iostream>
#include <unistd.h>
#include <cassert>
#include <cstring>
#include <sys/types.h>
#include <sys/wait.h>

#define MAX 1024

using namespace std;

int main()
{
    // 第一步，建立管道
    int pipefd[2] = {0};
    int n = pipe(pipefd);
    assert(n == 0);
    (void)n; // 在release版本调试下，assert会被注释掉，本句代码只做防止编译器告警的作用

    cout << "pipefd[0]:" << pipefd[0] << ", pipefd[1]:" << pipefd[1] << endl;

    // 第二步，创建子进程
    pid_t id = fork();

    if (id < 0)
    {
        perror("fork");
        return 1;
    }

    if (id == 0)
    {
        // child
        // w - 这里只是向管道文件中写入，并没有向显示屏中写入
        close(pipefd[0]);

        int cnt = 0;
        while (1)
        {
            char message[MAX];
            snprintf(message,sizeof(message),"Hello father , i am child , pid : %d , cnt : %d" , getpid(),cnt);
            write(pipefd[1],message,strlen(message));
            cnt++;
            if(cnt == 3)
            {
                cout << "child close w point" << endl;
                break;
            }
            sleep(1);
        }

        // close(pipefd[1]);

        exit(0);
    }

    // 第三步，关闭父子进程不需要的fd，形成单向信道
    // 父进程读，子进程写

    // father
    // r - 这里向管道中读取数据
    close(pipefd[1]);

    char buffer[MAX];
    while(1)
    {
        ssize_t num = read(pipefd[0],buffer,sizeof(buffer)-1);
        // 我们这里默认读到字符串,如果缓冲区中的数据长度超过了1024
        // 我们需要在结尾处留一个位置，用来存放/0
        if(num > 0)
        {
            buffer[num] = '\0';
            cout << getpid() << " , child say :" << buffer << " to me!" << endl;  
        }
        if(num == 0)
        {
            cout << "child quit , me too" << endl;
            break;
        }
        cout << "father return val(num):" << num << endl;

        sleep(1);
    }

    pid_t rid = wait(NULL);
    if (rid == id)
    {
        cout << "wait success" << endl;
    }

    return 0;
}
